# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: inkyu

import json

from coin.base.timestamp import get_timestamp
from google.protobuf.json_format import MessageToDict
from coin.exchange.base.strategy_logger import StrategyLogProvider
from coin.proto.coin_strategy_pb2 import StrategyLog
from coin.proto.coin_request_pb2 import StrategyRequestProto, StrategyInfoProto
from coin.proto.coin_feed_pb2 import BestBookEntry, BookEntry
from coin.proto.coin_order_gateway_pb2 import OrderGatewayLog
from coin.proto.coin_query_pb2 import AccountBalance


def _gen_info(revision):
  return StrategyInfoProto(revision=revision)


def _gen_request(name):
  return StrategyRequestProto(strategy_name=name)


class StrategyLoggerWrapper(object):
  def __init__(self, *, name, revision):
    assert len(name) > 7, name
    assert len(revision) == 8, revision
    self._name = name
    self._revision = revision

    self._request = _gen_request(name)
    self._log_provider = StrategyLogProvider(self._request)
    self._info = _gen_info(revision)

    self._book_cache = {}
    self._balance_cache = {}

  def _write(self, payload):
    self._log_provider.write(payload)

  def write_request(self, *, flush: bool = True):
    log_proto = StrategyLog(type=StrategyLog.STRAT_REQUEST, request=self._request)
    self._write(log_proto)

  def write_reserve(self, protobuf, *, flush: bool = True):
    assert isinstance(protobuf, AccountBalance)
    log_proto = StrategyLog(type=StrategyLog.RESERVE, reserve=protobuf)
    self._write(log_proto)

  def write_master_prices(self, master_prices):
    jsoned = {'ema_prices': master_prices}
    payload = StrategyLog(info=self._info,
                          type=StrategyLog.EXTRA_INFO,
                          extra_info=json.dumps(jsoned))
    self._write(payload)

  def write_pnl_snapshot(self, exchange_id, pnl_snapshot):
    payload = StrategyLog(info=self._info,
                          subreq_id=exchange_id,
                          type=StrategyLog.PNL_BALANCE,
                          reserve=pnl_snapshot.reserve,
                          quote=pnl_snapshot.quote,
                          balance=pnl_snapshot.balance,
                          position=pnl_snapshot.position,
                          pnl_balance=pnl_snapshot.pnl_balance)
    self._write(payload)

  def write_book(self,
                 exchange_id,
                 product,
                 true_price,
                 ask0_price,
                 bid0_price,
                 ask0_qty,
                 bid0_qty,
                 askt_price,
                 bidt_price):
    payload = StrategyLog(
        info=self._info,
        subreq_id=exchange_id,
        type=StrategyLog.BEST_BOOK,
        best_book_entry=BestBookEntry(
            symbol=product,
            true_price=true_price,
            ask0=BookEntry(price_float=ask0_price, qty_float=ask0_qty),
            bid0=BookEntry(price_float=bid0_price, qty_float=bid0_qty),
            askt=BookEntry(price_float=askt_price),
            bidt=BookEntry(price_float=bidt_price),
        ),
    )
    prev = self._book_cache.get((exchange_id, product))
    if prev == payload:
      return
    self._book_cache[exchange_id, product] = payload
    self._prev = payload
    self._write(payload)

  def write_og_log(self, exchange_id, protobuf):
    if protobuf.type == OrderGatewayLog.BALANCE:
      prev = self._balance_cache.get(exchange_id)
      if prev == protobuf:
        return
      self._balance_cache[exchange_id] = protobuf

    payload = StrategyLog(info=self._info,
                          subreq_id=exchange_id,
                          type=StrategyLog.OG_LOG,
                          og_log=protobuf)

    self._write(payload)
